// $ANTLR 2.7.6 (2005-12-22): "resources/grammars/PortLabelParser.g" -> "PortLabelParser.java"$

package com.cea.papyrus.classdiagram.parsers.antlr;

import org.eclipse.uml2.uml.*;
import java.util.Iterator;
import java.util.Collection;
import java.util.Vector;
import java.util.Map;

import com.cea.papyrus.classdiagram.parsers.util.Assert;
import com.cea.papyrus.classdiagram.parsers.texteditor.portlabel.IPortContext;

import com.cea.papyrus.umlutils.Parameter;

import antlr.TokenBuffer;
import antlr.TokenStreamException;
import antlr.TokenStreamIOException;
import antlr.ANTLRException;
import antlr.LLkParser;
import antlr.Token;
import antlr.TokenStream;
import antlr.RecognitionException;
import antlr.NoViableAltException;
import antlr.MismatchedTokenException;
import antlr.SemanticException;
import antlr.ParserSharedInputState;
import antlr.collections.impl.BitSet;

public class PortLabelParser extends antlr.LLkParser       implements PortLabelParserTokenTypes
 {

	public PortLabelParser(TokenStream lexer, Port port) {
		this(lexer);
		this.port = port;	
		this.nearestPackage = new com.cea.papyrus.umlutils.Package(port.getNearestPackage());
	}
	
	/**
	 * Validation state (true = validation : does not modify the port
	 */
	private boolean isValidation = false;
	
	/**
	 * @return the isValidation boolean
	 */
	public boolean isValidation() {
		return isValidation;
	}

	/**
	 * @param isValidation the isValidation to set (true -> do not modify the port)
	 */
	public void setValidation(boolean isValidation) {
		this.isValidation = isValidation;
	}
		private com.cea.papyrus.umlutils.Package nearestPackage;
	
	/**
	 * Modified Port 
	 */
	private Port port;
	
	/**
	 * @return the modified uml2 port
	 */
	public Port getPort() {
		return port;
	}

	/**
	 * @param port the port to set
	 */
	public void setPort(Port port) {
		this.port = port;
		nearestPackage = new com.cea.papyrus.umlutils.Package(port.getNearestPackage());
	}
    	
    // all possible modified ports on port (with default values : necessary ?!)
  	private String name;
    Type type=null;
    int lowerMultiplicity = 1;	// default multiplicity = [1..1]
    int upperMultiplicity = 1;	// default multiplicity = [1..1]
    
	/**
	 * Apply values to the port. <BR> 
	 * Modifications can not be applied directly. The parser must wait the end, 
	 * until it reaches the end of the label. If the end is reached without any error,
	 * new values can be applied to the target port.
	 */
	@SuppressWarnings("unchecked")
	private void applyValues() {
		if(!isValidation){
			debug("\nvalues applied :");
			debug("+  name: "+name);
			debug("+  type: "+type);
			debug("+  lower Multiplicity: "+lowerMultiplicity);
			debug("+  upper Multiplicity: "+upperMultiplicity);
			
			port.setName(name);
			port.setType(type);
			port.setLower(lowerMultiplicity);
			port.setUpper(upperMultiplicity);
		} 
	}
	
	 /** debug mode */
    protected final boolean debugMode = false;  	
    	
    /**
     * Debug method (~System.out.println)
     */
    private void debug(Object debug) {
    	if(debugMode) {
    		System.out.println(debug);	
    	}	
    }
    
     /**
     * Error method (~System.err.println)
     */
    private void error(Object debug) {
    	if(debugMode) {
    		System.err.println(debug);	
    	}	
    }
 
 		// vector that keeps modifiers already used (used for completion)
	public Map<String, Boolean> modifiersUsed; 
	
	/**
	 * @return the modifiersUsed
	 */
	public Map<String, Boolean> getModifiersUsed() {
		return modifiersUsed;
	}

	/**
	 * @param modifiersUsed the modifiersUsed to set
	 */
	public void setModifiersUsed(Map<String, Boolean> modifiersUsed) {
		this.modifiersUsed = modifiersUsed;
	}   
	
	 /**
     * Context (for completion processor)
     */
    private int context = IPortContext.DEFAULT;
    
    /**
	 * @return the context
	 */
	public int getContext() {
		return context;
	}

	/**
	 * @param context the context to set
	 */
	public void setContext(int context) {
		this.context = context;
	}
    

protected PortLabelParser(TokenBuffer tokenBuf, int k) {
  super(tokenBuf,k);
  tokenNames = _tokenNames;
}

public PortLabelParser(TokenBuffer tokenBuf) {
  this(tokenBuf,2);
}

protected PortLabelParser(TokenStream lexer, int k) {
  super(lexer,k);
  tokenNames = _tokenNames;
}

public PortLabelParser(TokenStream lexer) {
  this(lexer,2);
}

public PortLabelParser(ParserSharedInputState state) {
  super(state,2);
  tokenNames = _tokenNames;
}

	public final void label() throws RecognitionException, TokenStreamException {
		
		
		{
		_loop3:
		do {
			if ((LA(1)==WS)) {
				match(WS);
			}
			else {
				break _loop3;
			}
			
		} while (true);
		}
		name();
		{
		switch ( LA(1)) {
		case WS:
		case COLON:
		{
			{
			switch ( LA(1)) {
			case WS:
			{
				{
				{
				int _cnt8=0;
				_loop8:
				do {
					if ((LA(1)==WS)) {
						match(WS);
					}
					else {
						if ( _cnt8>=1 ) { break _loop8; } else {throw new NoViableAltException(LT(1), getFilename());}
					}
					
					_cnt8++;
				} while (true);
				}
				match(COLON);
				}
				break;
			}
			case COLON:
			{
				match(COLON);
				break;
			}
			default:
			{
				throw new NoViableAltException(LT(1), getFilename());
			}
			}
			}
			
						context = IPortContext.AFTER_COLON;
					
			port_type();
			context = IPortContext.TYPE;
			break;
		}
		case EOF:
		case LSQUARE:
		{
			break;
		}
		default:
		{
			throw new NoViableAltException(LT(1), getFilename());
		}
		}
		}
		{
		{
		switch ( LA(1)) {
		case LSQUARE:
		{
			multiplicity();
			context = IPortContext.MULTIPLICITY;
			{
			_loop12:
			do {
				if ((LA(1)==WS)) {
					match(WS);
				}
				else {
					break _loop12;
				}
				
			} while (true);
			}
			break;
		}
		case EOF:
		{
			break;
		}
		default:
		{
			throw new NoViableAltException(LT(1), getFilename());
		}
		}
		}
		}
		
				applyValues();
			
	}
	
	public final void name() throws RecognitionException, TokenStreamException {
		
		Token  id = null;
		
		id = LT(1);
		match(IDENTIFIER);
		
				name = id.getText();
			
	}
	
	public final void port_type() throws RecognitionException, TokenStreamException {
		
		
		{
		_loop16:
		do {
			if ((LA(1)==WS)) {
				match(WS);
			}
			else {
				break _loop16;
			}
			
		} while (true);
		}
		{
		switch ( LA(1)) {
		case IDENTIFIER:
		{
			type();
			break;
		}
		case LT:
		{
			match(LT);
			match(LITERAL_Undefined);
			match(GT);
			break;
		}
		default:
		{
			throw new NoViableAltException(LT(1), getFilename());
		}
		}
		}
	}
	
	public final void multiplicity() throws RecognitionException, TokenStreamException {
		
		
		match(LSQUARE);
		context = IPortContext.IN_MULTIPLICITY;
		{
		if ((LA(1)==INTEGER) && (LA(2)==POINT_POINT)) {
			lowerMultiplicity();
			match(POINT_POINT);
			upperMultiplicity();
			
						if(lowerMultiplicity > upperMultiplicity && upperMultiplicity != -1) {
							throw new RecognitionException("Lower bound ("+lowerMultiplicity+") is greater than upper bound ("+upperMultiplicity+")");
						}
					
		}
		else if ((LA(1)==INTEGER||LA(1)==STAR) && (LA(2)==RSQUARE)) {
			upperMultiplicity();
			
						if(upperMultiplicity == -1) {
							lowerMultiplicity = 0;
						} else {
							lowerMultiplicity = upperMultiplicity;
						}
					
		}
		else {
			throw new NoViableAltException(LT(1), getFilename());
		}
		
		}
		match(RSQUARE);
	}
	
	public final void type() throws RecognitionException, TokenStreamException {
		
		Token  id = null;
		
		id = LT(1);
		match(IDENTIFIER);
		
				String typeName = id.getText();
				com.cea.papyrus.umlutils.Type utilType = nearestPackage.findTypeByName(typeName);
				// type = findTypeByName(typeName, port);
				if(utilType != null) {
					type = utilType.getUml2Type();
				} else {
					throw new RecognitionException("Type "+typeName+" not found for port "+name);
				}
			
	}
	
	public final void lowerMultiplicity() throws RecognitionException, TokenStreamException {
		
		Token  in = null;
		
		in = LT(1);
		match(INTEGER);
		
				lowerMultiplicity = Integer.parseInt(in.getText());
			
	}
	
	public final void upperMultiplicity() throws RecognitionException, TokenStreamException {
		
		
		upperMultiplicity=unlimitedNatural();
	}
	
	public final int  unlimitedNatural() throws RecognitionException, TokenStreamException {
		int value = 0 ;
		
		Token  in = null;
		
		{
		switch ( LA(1)) {
		case STAR:
		{
			match(STAR);
			value = -1;
			break;
		}
		case INTEGER:
		{
			in = LT(1);
			match(INTEGER);
			value = Integer.parseInt(in.getText());
			break;
		}
		default:
		{
			throw new NoViableAltException(LT(1), getFilename());
		}
		}
		}
		return value;
	}
	
	
	public static final String[] _tokenNames = {
		"<0>",
		"EOF",
		"<2>",
		"NULL_TREE_LOOKAHEAD",
		"WS",
		"COLON",
		"IDENTIFIER",
		"LT",
		"\"Undefined\"",
		"GT",
		"LSQUARE",
		"POINT_POINT",
		"RSQUARE",
		"INTEGER",
		"STAR",
		"NL",
		"QUESTION_MARK",
		"LNOT",
		"DOUBLE_QUOTE",
		"SINGLE_QUOTE",
		"LPAREN",
		"RPAREN",
		"LCURLY",
		"DOUBLE_LCURLY",
		"RCURLY",
		"DOUBLE_RCURLY",
		"LOGICAL_AND",
		"DOUBLE_LOGICAL_AND",
		"PIPE",
		"DOUBLE_PIPE",
		"POINT",
		"COMMA",
		"SEMI",
		"SHARP",
		"TILDE",
		"DOUBLE_COLON",
		"RULE_ASSIGN",
		"ARROW",
		"DIV",
		"PLUS",
		"MINUS",
		"EQ",
		"ISEQ",
		"ISNE",
		"DOUBLE_LT",
		"LE",
		"DOUBLE_GT",
		"GE",
		"INCR",
		"DECR",
		"CALLOPERATION",
		"DIGIT",
		"ALPHA",
		"UNDERSCORE",
		"REAL",
		"REAL_OR_INT"
	};
	
	
	}
